#include "02_TaskQueue.hpp"
#include <stdio.h>

#define log() \
    printf("%s | %d | %s :debug \n", __FILE__, __LINE__, __FUNCTION__);

template<typename T>
TaskQueue<T>::TaskQueue(int queue_max_size)
    :_queue(queue<T>())
    ,_queue_max_size(queue_max_size)
    ,_mutex()
    ,_notfull()
    ,_notempty()
    ,_is_exit(false)
{}

template<typename T>
bool TaskQueue<T>::empty()
{
    return _queue.size() == 0;
}

template<typename T>
bool TaskQueue<T>::full()
{
    return static_cast<int>(_queue.size()) == _queue_max_size;
}

template<typename T>
void TaskQueue<T>::push(const T& data)
{
    Mutex::LockGuard lock(_mutex);

    while(full())
    {
        _notfull.wait(_mutex);
    }

    _queue.push(data);
    
    _notempty.notify_one();

}

template<typename T>
T TaskQueue<T>::pop()
{
    Mutex::LockGuard lock(_mutex);

    while(empty() && _is_exit == false)
    {
        _notempty.wait(_mutex);
    }

    if(_is_exit == false)
    {
        T data = _queue.front();
        _queue.pop();

        _notfull.notify_one();
        return data;
    }
    else
    {
        log();
        return nullptr;
    }

}

template<typename T>
void TaskQueue<T>::wakeup()
{
    _is_exit = true;
    _notempty.notify_all();
    //_notfull.notify_all();  // 不管了，我生气了，都醒醒，一个也别想睡
    log();
}
